﻿namespace Sai.Core
{
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.IO;
	using Sai.Core.Introspection;
    using System.Text;
    using System.Xml.Serialization;

	// enum type 
	public enum TypeChangeReason
	{
		Unknown,
		TypeTaxonomy, // was class, now interface etc.
		TypeSealed, // is now sealed
		TypeAbstract, // is now abstract
		TypeInheritance, // derivation changed.
		TypeInterfaceRemoved, // interface changed.
        TypeInterfaceAdded,
        // constants
        ConstantObsolete,
        ConstantRemoved,
        ConstantChanged,
        ConstantAdded,
        // fields
        FieldObsolete,
        FieldRemoved,
        FieldChanged,
        FieldAdded,
        // constructors
        ConstructorObsolete,
        ConstructorRemoved,
        ConstructorChanged,
        ConstructorAdded,
        // finalizer
        FinalizerAdded,
        FinalizerRemoved,
        // events
        EventObsolete,
        EventRemoved,
        EventChanged,
        EventAdded,
        // properties
        PropertyObsolete,
        PropertyRemoved,
        PropertyChanged,
        PropertyAdded,
        // indexers
        IndexerObsolete,
        IndexerRemoved,
        IndexerChanged,
        IndexerAdded,
        // methods
        MethodObsolete,
        MethodRemoved,
        MethodChanged,
        MethodAdded,
        // enum values
        EnumObsolete,
        ValueRemoved, 
        ValueAdded,
        ValueChanged
    }

    public static class TypeChangeReasonExtensions
    {
        public static bool IsObsolete(this TypeChangeReason reason)
        {
            return reason == TypeChangeReason.ConstantObsolete
            || reason == TypeChangeReason.FieldObsolete
            || reason == TypeChangeReason.ConstructorObsolete
            || reason == TypeChangeReason.EventObsolete
            || reason == TypeChangeReason.PropertyObsolete
            || reason == TypeChangeReason.IndexerObsolete
            || reason == TypeChangeReason.MethodObsolete
            || reason == TypeChangeReason.EnumObsolete;
        }

        public static bool IsAddition(this TypeChangeReason reason)
        {
            return reason == TypeChangeReason.TypeInterfaceAdded
            || reason == TypeChangeReason.ConstantAdded
            || reason == TypeChangeReason.FieldAdded
            || reason == TypeChangeReason.ConstructorAdded
            || reason == TypeChangeReason.FinalizerAdded
            || reason == TypeChangeReason.EventAdded
            || reason == TypeChangeReason.PropertyAdded
            || reason == TypeChangeReason.IndexerAdded
            || reason == TypeChangeReason.MethodAdded
            || reason == TypeChangeReason.ValueAdded;
        }

        public static bool IsRemoval(this TypeChangeReason reason)
        {
		    return reason == TypeChangeReason.TypeInterfaceRemoved
            || reason == TypeChangeReason.ConstantRemoved
            || reason == TypeChangeReason.FieldRemoved
            || reason == TypeChangeReason.ConstructorRemoved
            || reason == TypeChangeReason.FinalizerRemoved
            || reason == TypeChangeReason.EventRemoved
            || reason == TypeChangeReason.PropertyRemoved
            || reason == TypeChangeReason.IndexerRemoved
            || reason == TypeChangeReason.MethodRemoved
            || reason == TypeChangeReason.ValueRemoved;
        }

        public static bool IsChange(this TypeChangeReason reason)
        {
            return reason == TypeChangeReason.TypeTaxonomy
               || reason == TypeChangeReason.TypeSealed
               || reason == TypeChangeReason.TypeAbstract
               || reason == TypeChangeReason.TypeInheritance
               || reason == TypeChangeReason.ConstantChanged
               || reason == TypeChangeReason.FieldChanged
               || reason == TypeChangeReason.ConstructorChanged
               || reason == TypeChangeReason.EventChanged
               || reason == TypeChangeReason.PropertyChanged
               || reason == TypeChangeReason.IndexerChanged
               || reason == TypeChangeReason.MethodChanged
               || reason == TypeChangeReason.ValueChanged;
        }
    }

    public interface ITypeDifference : IFlattenToXml
	{
		string SummaryIdentifier { get; set; }

		string SummaryName { get; set; }

		string AssemblyIdentifier { get; set; }

		string AssemblyName { get; set; }

		string Identifier { get; set; }

        string FullName { get; }

        string NamespaceName { get; set; }

        string Name { get; set; }

		string FromVersion { get; set; }

		string ToVersion { get; set; }

        SourceCode SourceDefinition { get; set; }
        
		bool HasChanged { get; }

		void SaveTo(string fileName);

		void SaveTo(TextWriter writer);
        		
		void IdentifiedChange(IDiscoveredTypeChange change);

        void IdentifiedChange(TypeChangeReason reason, ISourceCodeProvider code);

        void IdentifiedChange(TypeChangeReason reason, ISourceCodeProvider code, string message);
	}
}
